<template>
  <div class="ckeditor" style="min-width: 0;">
    <div v-if="!Object.keys($store.state.currentUser).length" class="editor-shade">
      请先&nbsp;<el-button size="mini" type="primary" @click="goSignIn">登录</el-button>&nbsp;后发表评论
    </div>
    <div v-if="readonly" :class="ckClass" v-html="contentATagTarget"></div>
    <ckeditor v-else :editor="editor" v-model="editorData" :disabled="readonly" @ready="onReady"/>
  </div>
</template>

<script>
import CKEditor from '@ckeditor/ckeditor5-vue';
import DecoupledEditor from '../../../static/ckeditor';

class UploadImageAdapter {
  constructor(vue, loader) {
    this.vue = vue;
    this.loader = loader;
  }
  async isImage() {
    const file = await this.loader.file;
    return /^image\/[a-zA-Z]+/.test(file.type);
  }
  getUploadToken() {
    return new Promise((resolve, reject) => {
      this.vue.$api.other.uploadToken()
        .then(res => resolve(res.data.token))
        .catch((err) => {
          this.vue.$message.error('获取上传密钥失败', err);
          reject(err);
        });
    });
  }
  async upload() {
    const img = await this.loader.file;
    if (!/^image\/[a-zA-Z]+/.test(img.type)) { // 插件本身就拦截了非图片的文件，但是没有提醒，这里其实没用上
      this.vue.$message.error('请选择正确类型的图片文件！');
      return Promise.reject(false);
    }
    const uploadToken = await this.getUploadToken();
    const formData = new FormData();
    formData.append('file', img);
    formData.append('token', uploadToken);
    formData.append('key', `ck-images-${new Date().getTime()}/${img.name}`);
    formData.append('x:user_id', this.vue.$store.state.currentUser.id);

    return new Promise((resolve, reject) => {
      this.vue.$api.other.upload(formData)
        .then(res => resolve({ default: res.url }))
        .catch((err) => {
          this.vue.$message.error('图片上传失败', err);
          reject(err);
        });
    });
  }
  // eslint-disable-next-line class-methods-use-this
  abort() {}
}

export default {
  name: 'CKEditor', // 富文本编辑器
  components: {
    ckeditor: CKEditor.component,
  },
  props: {
    readonly: { // 编辑器只读
      type: Boolean,
      default: false,
    },
    initialContent: { // 初始内容
      type: String,
      default: '',
    },
    content: { // 用于实时更新富文本内容
      type: String,
      required: false,
    },
    lazy: { // 是否快速加载html后刷新为富文本
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      editor: DecoupledEditor,
      editorData: this.initialContent,
      quickShow: this.lazy,
    };
  },
  computed: {
    // 快速加载div，匹配一样的样式
    ckClass() {
      const classList = 'ck-blurred ck ck-content ck-editor__editable ck-rounded-corners ck-editor__editable_inline';
      return this.readonly ? `${classList} ck-read-only` : classList;
    },
    // 直接html时，给a标签加上target
    contentATagTarget() {
      return this.initialContent.replace('<a href="', '<a target="_blank" href="');
    },
  },
  methods: {
    // 编辑器就绪
    async onReady(editor) {
      if (!this.readonly) { // 非已读的时候生成工具栏
        await editor.ui.getEditableElement().parentElement.insertBefore(
          editor.ui.view.toolbar.element,
          editor.ui.getEditableElement(),
        );
        // 配置图片上传到七牛
        // eslint-disable-next-line no-param-reassign
        editor.plugins.get('FileRepository').createUploadAdapter = loader => new UploadImageAdapter(this, loader);
      }
    },
    // 清空编辑器
    clearContent() { this.editorData = ''; },
    // 前往登录页面
    goSignIn() {
      const path = `/${this.$rp.USERS}/${this.$rp.SIGN_IN}`;
      const query = { redirect: this.$route.fullPath };
      this.$root.$emit('routerPush', { path, query });
    },
  },
  mounted() {
    const that = this;
    const time = setTimeout(() => {
      that.quickShow = false;
      clearTimeout(time);
    }, 500);
  },
  watch: {
    // 实时更新编辑器数据
    editorData() { this.$emit('update:content', this.editorData); },
  },
};
</script>

<style lang="scss">
.editor-shade { display: none; }

:root { --ck-color-toolbar-border: #c4c4c4; }
.ck.ck-editor__editable_inline:not(.ck-read-only) { border-color: var(--ck-color-toolbar-border); }

.main-reply,
.floor-reply {

  .ck-editor__editable_inline { min-height: 7.25rem; }

  .ckeditor {
    position: relative;

    .editor-shade{
      display: flex;
      justify-content: center;
      align-items: center;
      position: absolute;
      z-index: 100;
      top: 0; bottom: 0;
      left: 0; right: 0;
      border-radius: 2px;
      background-color: #C0C4CC;
    }
  }
}

.ck.ck-content .table table td { border: 1px solid #d9d9d9; }
.ck.ck-content a {
  text-decoration: underline;
  color: -webkit-link;
}

#space-issues-update,
#space-issues-create {
  .ck-editor__editable_inline { min-height: 14.5rem; }
}

#space-resource-update,
#space-resource-create,
#feedback-create {
  .ck-editor__editable_inline { min-height: 28rem; }
}

.ckeditor.h-mini .ck-editor__editable_inline { min-height: 7.5rem; }
.ckeditor.h-small .ck-editor__editable_inline { min-height: 14.5rem; }
.ckeditor.h-issue-create .ck-editor__editable_inline { min-height: 20rem; }
.ckeditor.h-normal .ck-editor__editable_inline { min-height: 28rem; }

.ck-toolbar + .ck-content.ck-editor__editable_inline {
  max-height: 80vh;
  overflow-y: scroll;
}
</style>
